package org.duiduo.utils;

import org.apache.commons.lang.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 类说明:日期处理类
 */
public class DateUtil {
	
	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static final String DATE_FORMAT_1 = "yyyy-MM-dd HH:mm:ss";
	/**
	 * yyyyMMddHHmmss
	 */
	public static final String DATE_FORMAT_2 = "yyyyMMddHHmmss";
	/**
	 * yyyyMMdd
	 */
	public static final String DATE_FORMAT_3 = "yyyyMMdd";
	/**
	 * HHmmss
	 */
	public static final String DATE_FORMAT_4 = "HHmmss";
	/**
	 * HH
	 */
	public static final String DATE_FORMAT_5 = "HH";
	/**
	 * yyyy-MM-dd
	 */
	public static final String DATE_FORMAT_6 = "yyyy-MM-dd";
	/**
	 * yyyyMMddHHmm
	 */
	public static final String DATE_FORMAT_7 = "yyyyMMddHHmm";
	/**
	 * MMddHHmmss
	 */
	public static final String DATE_FORMAT_8 = "MMddHHmmss";
	/**
	 * yyyyMMdd HH:mm:ss
	 */
	public static final String DATE_FORMAT_9 = "yyyyMMdd HH:mm:ss";
	/**
	 * MMdd
	 */
	public static final String DATE_FORMAT_10 = "MMdd";
	/**
	 * HH:mm:ss
	 */
	public static final String DATE_FORMAT_11 = "HH:mm:ss";
	
	/**
	 * yyyyMMddHHmmssSSS
	 * 
	 */
	public static final String DATE_FORMAT_12 = "yyyyMMddHHmmssSSS";
	
	/**
	 * yyyyMMddHHmmssSSS
	 * 
	 */
	public static final String DATE_FORMAT_13 = "yyMMddHHmmssSSS";
	
	/**
	 * yyyyMMdd HHmmss
	 */
	public static final String DATE_FORMAT_14 = "yyyyMMdd HHmmss";
	
	/**
	 * HHmm
	 */
	public static final String DATE_FORMAT_15 = "HHmm";

	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public static final String DATE_FORMAT_16 = "yyyy-MM-dd HH";
	
	private static Map<String, ThreadLocal<SimpleDateFormat>> mapThreadLocal = new HashMap<String, ThreadLocal<SimpleDateFormat>>();
	private static final Object lockObj = new Object();
	private static DateUtil classInstance = new DateUtil();

	public static DateUtil getInstance() {
		return classInstance;
	}

	public static SimpleDateFormat getSimpleDateFormat(final String pattern) {
		ThreadLocal<SimpleDateFormat> df = mapThreadLocal.get(pattern);
		if (df == null) {
			synchronized (lockObj) {
				df = mapThreadLocal.get(pattern);
				if (df == null) {
					df = new ThreadLocal<SimpleDateFormat>() {
						@Override
						protected SimpleDateFormat initialValue() {
							return new SimpleDateFormat(pattern);
						}
					};
					mapThreadLocal.put(pattern, df);
				}
			}
		}
		return df.get();
	}
	
	/**
	 * 日期转字符串
	 * @param date
	 * @param pattern
	 * @return
	 */
	public static String formatDate(Date date, String pattern){
		String riqi = null;
		if(date != null && StringUtils.isNotBlank(pattern)){
			SimpleDateFormat dateFormat = getSimpleDateFormat(pattern);
			riqi =  dateFormat.format(date);
		}
		return riqi;
	}
	
	/**
	 * 字符串转日期
	 * @param date
	 * @param pattern
	 * @return
	 * @throws ParseException
	 */
	public static Date formatDate(String date, String pattern) throws ParseException {
		Date rq = null;
		if(StringUtils.isNotBlank(date) && StringUtils.isNotBlank(pattern)){
			SimpleDateFormat dateFormat = getSimpleDateFormat(pattern);
			try {
				rq = dateFormat.parse(date);
			} catch (ParseException e) {
				throw e;
			}
		}
		return rq;
	}
	
	/**
	 * 获取当前时间
	 * @param pattern : 格式化
	 * @return
	 */
	public static String getTime(String pattern) {
		return getSimpleDateFormat(pattern).format(new Date());
	}
	
	
	/**
	 * 日期相加
	 * @param date : 日期
	 * @param pattern : 格式化
	 * @param subInt : 减的天数
	 * @return
	 * @throws ParseException
	 */
	public static String dateAdd(String date, String pattern, int field, int addInt) throws ParseException {
		SimpleDateFormat dateFormat = getSimpleDateFormat(pattern);
		Date rq = dateFormat.parse(date);
		Calendar cdate = Calendar.getInstance();
		cdate.setTime(rq);
		cdate.set(field, cdate.get(field) + addInt);
		return dateFormat.format(cdate.getTime());
	}
	
	/**
	 * 日期相加
	 * @param date : 日期
	 * @param pattern : 格式化
	 * @param subInt : 减的天数
	 * @return
	 * @throws ParseException
	 */
	public static Date dateAdd(Date date, String pattern, int field, int addInt) throws ParseException {
		Calendar cdate = Calendar.getInstance();
		cdate.setTime(date);
		cdate.set(field, cdate.get(field) + addInt);
		return cdate.getTime();
	}
	
	/**
	 * 日期相减
	 * @param date : 日期
	 * @param pattern : 格式化
	 * @param subInt : 减的天数
	 * @return
	 * @throws ParseException
	 */
	public static String dateSub(String date, String pattern, int subInt) throws ParseException {
		SimpleDateFormat dateFormat = getSimpleDateFormat(pattern);
		Date rq = dateFormat.parse(date);
		Calendar cdate = Calendar.getInstance();
		cdate.setTime(rq);
		cdate.set(Calendar.DATE, cdate.get(Calendar.DATE) - subInt);
		return dateFormat.format(cdate.getTime());
	}
	
	
	/**
	 * 日期相减
	 * @param date : 日期
	 * @param pattern : 格式化
	 * @param subInt : 减的天数
	 * @return
	 * @throws ParseException
	 */
	public static Date dateSub(String date, String pattern, int field, int subInt) throws ParseException {
		SimpleDateFormat dateFormat = getSimpleDateFormat(pattern);
		Date rq = dateFormat.parse(date);
		Calendar cdate = Calendar.getInstance();
		cdate.setTime(rq);
		cdate.set(field, cdate.get(field) - subInt);
		return cdate.getTime();
	}
	
	/**
	 * 日期相减
	 * @param date : 日期
	 * @param pattern : 格式化
	 * @param subInt : 减的天数
	 * @return
	 * @throws ParseException
	 */
	public static Date dateSub(Date date, String pattern, int field, int subInt) throws ParseException {
		Calendar cdate = Calendar.getInstance();
		cdate.setTime(date);
		cdate.set(field, cdate.get(field) - subInt);
		return cdate.getTime();
	}
	
	/**
	 * 日期相减
	 * @param date : 日期
	 * @param pattern : 格式化
	 * @param subInt : 减的天数
	 * @return
	 * @throws ParseException
	 */
	public static String dateSub(Date date, String pattern, int subInt) throws ParseException {
		SimpleDateFormat dateFormat = getSimpleDateFormat(pattern);
		String date_str = dateFormat.format(date);
		Date rq = dateFormat.parse(date_str);
		Calendar cdate = Calendar.getInstance();
		cdate.setTime(rq);
		cdate.set(Calendar.DATE, cdate.get(Calendar.DATE) - subInt);
		return dateFormat.format(cdate.getTime());
	}
	
	public static String get_yyMMdd(Date date, String pattern, int subInt) throws ParseException {
		String date_str = dateSub(date, pattern, subInt);
		return date_str.substring(2);
	}
	
	/**
	 * 获取上一个月的第一天时间
	 * @param pattern
	 * @return
	 * @throws ParseException
	 */
	public static String getUpMonthFirstDay(String pattern) throws ParseException {
		Calendar cale = Calendar.getInstance();//获取当前日期
		cale.add(Calendar.MONTH, -1);
		cale.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天
		String firstDay = getSimpleDateFormat(pattern).format(cale.getTime());
		return firstDay;
	}
	
	/**
	 * 获取上一个月的最后一天时间
	 * @param pattern
	 * @return
	 * @throws ParseException
	 */
	public static String getUpMonthLastDay(String pattern) throws ParseException {
		Calendar cale = Calendar.getInstance();
		cale.add(Calendar.MONTH, 0);
		cale.set(Calendar.DAY_OF_MONTH,0);//设置为1号,当前日期既为本月第一天
		String lastDay = getSimpleDateFormat(pattern).format(cale.getTime());
		return lastDay;
	}

	public static boolean isDateAcrossMonth(String startdate, String enddate, String pattern, int val) throws Exception {
		try {
			SimpleDateFormat dateFormat = getSimpleDateFormat(DATE_FORMAT_6);
			Date star_rq = dateFormat.parse(startdate);
			Date end_rq = dateFormat.parse(enddate);
			
			Calendar cdate = Calendar.getInstance();
			cdate.setTime(star_rq);
			cdate.set(Calendar.MONTH, cdate.get(Calendar.MONTH) + val);
			
			return cdate.getTime().getTime() > end_rq.getTime();
		} catch (Exception e) {
			throw e;
		}
	}

	public static String getday(){
		long today = new Date().getTime();
		//获取2011-11-1距离1970-1-1的<a href="https://www.baidu.com/s?wd=%E6%AF%AB%E7%A7%92&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4uj--mW9hnWbvuywbPHR10ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPjbLnH03nHb3n1n4P1D1nj6Y" target="_blank" class="baidu-highlight">毫秒</a>数
		Calendar calendar = Calendar.getInstance();
		calendar.set(2011, 1, 1);
		long preDay = calendar.getTimeInMillis();
		//二者相减换算成天数取整（不足一天的忽略不计，如果要算，+1即可）
		return String.valueOf(((today - preDay) / (24 * 60 * 60 * 1000)));
	}

	/**
	 * 获取日期天数差
	 * @return
	 */
	public static int getDateDiff(String dateOne, String dateTwo, String pattern) throws Exception {
		try {
			SimpleDateFormat dateFormat = getSimpleDateFormat(pattern);
			Date dOne = dateFormat.parse(dateOne);
			Date dTwo = dateFormat.parse(dateTwo);
			long dTimeOne = dOne.getTime();
			long dTimeTwo = dTwo.getTime();
			return (int) ((dTimeTwo - dTimeOne) / (1000 * 60 * 60 * 24));
		} catch (Exception e) {
			throw e;
		}
	}

	/**
	 * 获取当月的最后一天
	 *
	 * @param pattern
	 * @return
	 * @throws ParseException
	 */
	public static String getCurrentMonthLastDay(String pattern) throws ParseException {
		Calendar cale = Calendar.getInstance();
		cale.add(Calendar.MONTH, 1);
		cale.set(Calendar.DAY_OF_MONTH, 0);//设置为1号,当前日期既为本月第一天
		String lastDay = getSimpleDateFormat(pattern).format(cale.getTime());
		return lastDay;
	}

	/**
	 * 获取当前日期到的本月最后一天日期列表[包括始终日期]
	 *
	 * @param currentDay
	 * @param pattern
	 * @return
	 * @throws Exception
	 * @since 3.0.3
	 */
	public static List<String> getCurrentDay2MonthLastDayDateList(String currentDay, String pattern) throws Exception {
		List<String> dateList = new ArrayList<String>();
		String currentDayYyyyMDd = currentDay.replaceAll("-", "");
		int year = Integer.parseInt(currentDayYyyyMDd.substring(0, 4));
		int month = Integer.parseInt(currentDayYyyyMDd.substring(4, 6));
		int day = Integer.parseInt(currentDayYyyyMDd.substring(6));
		Calendar cale = Calendar.getInstance();
		cale.set(year, month, day);
		cale.set(Calendar.DAY_OF_MONTH, 0);//设置为1号,当前日期既为本月第一天
		String currentMonthLastDay = getSimpleDateFormat(pattern).format(cale.getTime());
		int diff = getDateDiff(currentDay, currentMonthLastDay, pattern);
		for (int i = 0; i <= diff; i++) {
			dateList.add(dateAdd(currentDay, pattern, Calendar.DAY_OF_MONTH, i));
		}
		return dateList;
	}

	/**
	 * 日期转星期
	 * "星期日:1", "星期一:2", "星期二:3", "星期三:4", "星期四:5", "星期五:6", "星期六:7"
	 *
	 * @param datetime
	 * @return
	 */
	public static Integer dateToWeek(String datetime) {
		SimpleDateFormat f = new SimpleDateFormat(DATE_FORMAT_6);
		Integer[] weekDays = {1, 2, 3, 4, 5, 6, 7};
		Calendar cal = Calendar.getInstance(); // 获得一个日历
		Date datet = null;
		try {
			datet = f.parse(datetime);
			cal.setTime(datet);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
		if (w < 0)
			w = 0;
		return weekDays[w];
	}

	public static void main(String[] args) {
		try {
			Date date = new Date();
			System.out.println(date.toLocaleString());
			Date pay_time = DateUtil.dateSub(date, DateUtil.DATE_FORMAT_1, Calendar.MINUTE, 10);
			System.out.println(pay_time.toLocaleString());
			/**
			 * 获取上月的最后一天
			 */
			System.out.println("获取上月的最后一天:" + getUpMonthLastDay(DateUtil.DATE_FORMAT_1));
			/**
			 * 获取当月的最后一天
			 */
			System.out.println("获取当月的最后一天:" + getCurrentMonthLastDay(DateUtil.DATE_FORMAT_1));
			/**
			 * 获取当前日期到的本月最后一天日期列表
			 */
			System.out.println("获取当前日期到的本月最后一天日期列表:" + getCurrentDay2MonthLastDayDateList("2021-02-01", DATE_FORMAT_6));
		} catch (Exception e) {
		}
	}
}
